﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Security.Principal;
using System.Collections.Concurrent;
using Bzure.Common.Caching.WeakCaching;

namespace System
{
    public class Me
    {
        static ConcurrentDictionary<string, WeakStorageManager> _cacheManagerPool = new ConcurrentDictionary<string, WeakStorageManager>();
        static IDictionary<string, string> _themes = new Dictionary<string, string>();
        public string Name
        {
            get
            {
                return this.Principal.Identity.Name;
            }
        }
        public IPrincipal Principal
        {
            get;
            private set;
        }
        public Me(IPrincipal principal)
        {
            this.Principal = principal;
        }
        WeakStorageManager CacheManager
        {
            get
            {
                WeakStorageManager _cacheManager = default(WeakStorageManager);
                if (!this.Principal.Identity.IsAuthenticated)
                    return _cacheManager;
                if (!_cacheManagerPool.TryGetValue(this.Principal.Identity.Name, out _cacheManager))
                {
                    _cacheManager = new WeakStorageManager();
                    _cacheManagerPool[this.Principal.Identity.Name] = _cacheManager;
                }
                return _cacheManager;
            }
        }

        public T GetCached<T>(string CachedKey, Func<T> func, TimeSpan timespan, bool Cach = true) where T : class
        {
            if (!Cach)
                return func();
            return CacheManager.Get(CachedKey, func, timespan);
        }
        public void SetCached<T>(string CachedKey, T target, TimeSpan timespan) where T : class
        {
            CacheManager.Set(CachedKey, target, timespan);
        }
        public string ThemeName
        {
            get
            {
                if (!Actor.Public.IsAuthenticated)
                    return Actor.Public.ThemeName();
                string theme = null;
                if (!_themes.TryGetValue(this.Principal.Identity.Name, out theme))
                {
                    theme = Actor.Public.ThemeName();
                    _themes[this.Principal.Identity.Name] = theme;
                }
                return theme;
            }
            set
            {
                _themes[this.Principal.Identity.Name] = value;
            }
        }
        public void SignOut()
        {
            WeakStorageManager wsm = default(WeakStorageManager);
            if (_cacheManagerPool.ContainsKey(this.Principal.Identity.Name))
                _cacheManagerPool.TryRemove(this.Principal.Identity.Name, out wsm);
            if (_themes.ContainsKey(this.Principal.Identity.Name))
                _themes.Remove(this.Principal.Identity.Name);
        }
    }
    public class Public
    {
        public IPrincipal Principal
        {
            get;
            private set;
        }
        public Public(IPrincipal principal)
        {
            this.Principal = principal;
        }
        public bool IsAuthenticated
        {
            get
            {
                return this.Principal.Identity.IsAuthenticated;
            }
        }
        static WeakStorageManager _cacheManager = default(WeakStorageManager);
        WeakStorageManager CacheManager
        {
            get
            {
                if (_cacheManager == default(WeakStorageManager))
                {
                    _cacheManager = new WeakStorageManager();
                }
                return _cacheManager;
            }
        }

        public T GetCached<T>(string CachedKey, Func<T> func, TimeSpan timespan, bool Cach = true) where T : class
        {
            if (!Cach)
                return func();
            return CacheManager.Get(CachedKey, func, timespan);
        }
        public void SetCached<T>(string CachedKey, T target, TimeSpan timespan) where T : class
        {
            CacheManager.Set(CachedKey, target, timespan);
        }
        static Func<string> _themeName = () => "Default";
        public Func<string> ThemeName
        {
            get { return _themeName; }
            set { _themeName = value; }
        }
        static Func<string> _defaultArea = () => string.Empty;
        public Func<string> DefaultArea
        {
            get { return _defaultArea; }
            set { _defaultArea = value; }
        }
        public INull Blocks { get { return default(INull); } }
    }
    public static class Actor
    {
        public static Me Me
        {
            get
            {
                IPrincipal principal = default(IPrincipal);
                if (HttpContext.Current == default(HttpContext) || HttpContext.Current.User == default(IPrincipal))
                {
                    principal = Thread.CurrentPrincipal;
                }
                else
                {
                    principal = HttpContext.Current.User;
                }
                //if (!principal.Identity.IsAuthenticated)
                //    throw new System.Security.SecurityException("no authenticated");
                return new Me(principal);
            }
        }
        public static Public Public
        {
            get
            {
                IPrincipal principal = default(IPrincipal);
                if (HttpContext.Current == default(HttpContext) || HttpContext.Current.User == default(IPrincipal))
                {
                    principal = Thread.CurrentPrincipal;
                }
                else
                {
                    principal = HttpContext.Current.User;
                }
                return new Public(principal);
            }
        }
    }
}
